package com.gitee.wsl.android.ui.recyclerView.adapter

//package com.julive.adapter.ui.common

import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.gitee.wsl.android.ui.recyclerView.adapter.AdapterConfig.Companion.LAYOUT_TYPE_DEFAULT
import com.gitee.wsl.android.ui.recyclerView.callback.OnViewAttachStateChangeListener
import com.gitee.wsl.android.ui.recyclerView.callback.ViewAttachStateChangeListenerContainer
import com.gitee.wsl.ext.any.ifType
import java.lang.ref.WeakReference

open class WrapAdapter(private var mWrappedAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>) :
    RecyclerView.Adapter<RecyclerView.ViewHolder>(), WrapAdapterDataObserver.Subscriber,LayoutChangeSet,
    ViewAttachStateChangeListenerContainer {

    var layoutType:Int = LAYOUT_TYPE_DEFAULT


    private val emptyList by lazy {
        emptyList<Any>()
    }

    init {
        val wrapAdapterDataObserver =
            WrapAdapterDataObserver(WeakReference(this), WeakReference(mWrappedAdapter), null)
        mWrappedAdapter.registerAdapterDataObserver(wrapAdapterDataObserver)
        super.setHasStableIds(mWrappedAdapter.hasStableIds())
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return mWrappedAdapter.onCreateViewHolder(parent, viewType)
    }

    override fun getItemCount(): Int {
        return mWrappedAdapter.itemCount
    }

    override fun getItemId(position: Int): Long {
        return mWrappedAdapter.getItemId(position)
    }

    override fun getItemViewType(position: Int): Int {
        return mWrappedAdapter.getItemViewType(position)
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        onBindViewHolder(
            holder,
            position,
            emptyList
        )
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int, payloads: List<Any>) {
        mWrappedAdapter.onBindViewHolder(holder, position, payloads)
    }

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        mWrappedAdapter.onAttachedToRecyclerView(recyclerView)
    }

    override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
        mWrappedAdapter.onDetachedFromRecyclerView(recyclerView)
    }

    override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
        mWrappedAdapter.onViewAttachedToWindow(holder)
    }

    override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
        mWrappedAdapter.onViewDetachedFromWindow(holder)
    }

    override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
        mWrappedAdapter.onViewRecycled(holder)
    }

    override fun onFailedToRecycleView(holder: RecyclerView.ViewHolder): Boolean {
        return mWrappedAdapter.onFailedToRecycleView(holder)
    }

    fun getWrappedAdapter(): RecyclerView.Adapter<RecyclerView.ViewHolder> {
        return mWrappedAdapter
    }

    override fun onBridgedAdapterChanged(source: RecyclerView.Adapter<*>, tag: Any?) {
        notifyDataSetChanged()
    }

    override fun onBridgedAdapterItemRangeChanged(
        source: RecyclerView.Adapter<*>,
        tag: Any?,
        positionStart: Int,
        itemCount: Int
    ) {
        notifyItemRangeChanged(positionStart, itemCount)
    }

    override fun onBridgedAdapterItemRangeChanged(
        source: RecyclerView.Adapter<*>,
        tag: Any?,
        positionStart: Int,
        itemCount: Int,
        payload: Any?
    ) {
        notifyItemRangeChanged(positionStart, itemCount, payload)
    }

    override fun onBridgedAdapterItemRangeInserted(
        source: RecyclerView.Adapter<*>,
        tag: Any?,
        positionStart: Int,
        itemCount: Int
    ) {
        notifyItemRangeInserted(positionStart, itemCount)
    }

    override fun onBridgedAdapterItemRangeRemoved(
        source: RecyclerView.Adapter<*>,
        tag: Any?,
        positionStart: Int,
        itemCount: Int
    ) {
        notifyItemRangeRemoved(positionStart, itemCount)
    }

    override fun onBridgedAdapterRangeMoved(
        source: RecyclerView.Adapter<*>,
        tag: Any?,
        fromPosition: Int,
        toPosition: Int,
        itemCount: Int
    ) {
        notifyItemMoved(fromPosition, toPosition)
    }

    override fun layoutChange(layoutType: Int) {
        this.layoutType = layoutType
        if(mWrappedAdapter is LayoutChangeSet) {
            (mWrappedAdapter as LayoutChangeSet).layoutChange(layoutType)
        }
    }

    override fun addOnViewAttachStateChangeListener(listener: OnViewAttachStateChangeListener) {
        mWrappedAdapter.ifType<ViewAttachStateChangeListenerContainer> {
            it.addOnViewAttachStateChangeListener(listener)
        }
    }

    override fun removeOnViewAttachStateChangeListener(listener: OnViewAttachStateChangeListener) {
        mWrappedAdapter.ifType<ViewAttachStateChangeListenerContainer> {
            it.removeOnViewAttachStateChangeListener(listener)
        }
    }
}


class WrapAdapterDataObserver(
    private var mRefSubscriber: WeakReference<Subscriber>,
    private var mRefSourceHolder: WeakReference<RecyclerView.Adapter<*>>,
    private var mTag: Any? = null
) : RecyclerView.AdapterDataObserver() {

    interface Subscriber {
        fun onBridgedAdapterChanged(
            source: RecyclerView.Adapter<*>,
            tag: Any?
        )

        fun onBridgedAdapterItemRangeChanged(
            source: RecyclerView.Adapter<*>,
            tag: Any?,
            positionStart: Int,
            itemCount: Int
        )

        fun onBridgedAdapterItemRangeChanged(
            source: RecyclerView.Adapter<*>,
            tag: Any?,
            positionStart: Int,
            itemCount: Int,
            payload: Any?
        )

        fun onBridgedAdapterItemRangeInserted(
            source: RecyclerView.Adapter<*>,
            tag: Any?,
            positionStart: Int,
            itemCount: Int
        )

        fun onBridgedAdapterItemRangeRemoved(
            source: RecyclerView.Adapter<*>,
            tag: Any?,
            positionStart: Int,
            itemCount: Int
        )

        fun onBridgedAdapterRangeMoved(
            source: RecyclerView.Adapter<*>,
            tag: Any?,
            fromPosition: Int,
            toPosition: Int,
            itemCount: Int
        )
    }

    override fun onChanged() {
        val subscriber: Subscriber? = mRefSubscriber.get()
        val source = mRefSourceHolder.get()
        if (subscriber != null && source != null) {
            subscriber.onBridgedAdapterChanged(source, mTag)
        }
    }

    override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {
        val subscriber: Subscriber? = mRefSubscriber.get()
        val source = mRefSourceHolder.get()
        if (subscriber != null && source != null) {
            subscriber.onBridgedAdapterItemRangeChanged(source, mTag, positionStart, itemCount)
        }
    }

    override fun onItemRangeChanged(
        positionStart: Int,
        itemCount: Int,
        payload: Any?
    ) {
        val subscriber: Subscriber? = mRefSubscriber.get()
        val source = mRefSourceHolder.get()
        if (subscriber != null && source != null) {
            subscriber.onBridgedAdapterItemRangeChanged(
                source,
                mTag,
                positionStart,
                itemCount,
                payload
            )
        }
    }

    override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
        val subscriber: Subscriber? = mRefSubscriber.get()
        val source = mRefSourceHolder.get()
        if (subscriber != null && source != null) {
            subscriber.onBridgedAdapterItemRangeInserted(source, mTag, positionStart, itemCount)
        }
    }

    override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
        val subscriber: Subscriber? = mRefSubscriber.get()
        val source = mRefSourceHolder.get()
        if (subscriber != null && source != null) {
            subscriber.onBridgedAdapterItemRangeRemoved(source, mTag, positionStart, itemCount)
        }
    }

    override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
        val subscriber: Subscriber? = mRefSubscriber.get()
        val source = mRefSourceHolder.get()
        if (subscriber != null && source != null) {
            subscriber.onBridgedAdapterRangeMoved(source, mTag, fromPosition, toPosition, itemCount)
        }
    }

}